home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / Simple Slideshow / DialogUtils.c next >
Encoding:
C/C++ Source or Header  |  1996-10-29  |  33.9 KB  |  1,541 lines  |  [TEXT/CWIE]

  1. /*************************************************************************************************
  2. *
  3. *
  4. *        DialogUtils.c            - some useful odd bits to support dialogs
  5. *
  6. *
  7. *        19/7/94        ©1994, Graham Cox
  8. *
  9. *************************************************************************************************/
  10.  
  11. #include    "DialogUtils.h"
  12. #include    "ThreeDEffects.h"
  13. #include    "CursorUtilities.h"
  14. #include    "DynamicLinking.h"
  15. #include    "PrefManager.h"
  16. #include    "MenuUtils.h"
  17. #include    "CZoomChore.h"
  18. #include    "CApplication.h"
  19. #include    <fp.h>
  20. #include    <string.h>
  21. #include    <drag.h>
  22.  
  23. #ifndef __COLOURLAB__
  24. #define    __COLOURLAB__
  25. #endif
  26.  
  27.  
  28. typedef struct
  29. {
  30.     short    fieldID;
  31.     short    fieldType;
  32. }
  33. fieldInfo;
  34.  
  35.  
  36. typedef struct
  37. {
  38.     DialogPtr    theDlg;
  39.     short        itemID;
  40.     short        flags;
  41. }
  42. itemInfo;
  43.  
  44.  
  45. Rect    gDialogZoomRect = {0,0,0,0};
  46.  
  47. extern CApplication*    gApplication;
  48.  
  49.  
  50. static Handle        gFieldInfo = NULL;
  51. static itemInfo**    gExtraDialogInfo = NULL;                          
  52.  
  53. static short    GetFieldType(short theField);
  54. static Boolean    HasEditFields(DialogPtr theDialog);
  55.  
  56. void    OutlineDialogItem(DialogPtr theDialog,short theItem)
  57. {
  58.     GrafPtr        savePort;
  59.     Handle        itemHand;
  60.     short        itemType;
  61.     Rect        itemBox;
  62.     PenState    pnState;
  63.     
  64.     if (theDialog)
  65.     {
  66.         GetPort(&savePort);
  67.         SetPort(theDialog);
  68.         GetPenState(&pnState);
  69.         PenNormal();
  70.         PenMode(patCopy);
  71.         
  72.         GetDItem(theDialog,theItem,&itemType,&itemHand,&itemBox);
  73.         if ((itemType & 0x7F) == (ctrlItem + btnCtrl))
  74.         {
  75.             if ((*(ControlHandle)itemHand)->contrlHilite == 255)
  76.             {
  77.                 RGBColor grayRGB = {0x8888,0x8888,0x8888};
  78.                 RGBForeColor(&grayRGB);
  79.             }
  80.             InsetRect(&itemBox,-4,-4);
  81.             PenSize(3,3);
  82.             FrameRoundRect(&itemBox,16,16);
  83.             
  84.             ForeColor(blackColor);
  85.         }
  86.         SetPenState(&pnState);
  87.         SetPort(savePort);
  88.     
  89.     }
  90. }
  91.  
  92.  
  93.  
  94. pascal void        FrameRectUserItem(DialogPtr theDialog,short theItem)
  95. {
  96.     short        itemType;
  97.     Handle        itemHand;
  98.     Rect        itemBox;
  99.     
  100.     GetDItem(theDialog,theItem,&itemType,&itemHand,&itemBox);
  101.     Frame3DRect(&itemBox,kRecessedEmbossed);
  102.     FrameRect(&itemBox);
  103. }
  104.  
  105.  
  106. pascal void        FrameGrayRectUserItem(DialogPtr theDialog,short theItem)
  107. {
  108.     // draws a 50% grey outline around the item's rect. This checks for the special case of
  109.     // the item being less than 1 pixel wide or high, and if this is the case, draws a 3D
  110.     // line instead. This is generally OK because the most common use for this proc is to
  111.     // add decorative lines to dialog boxes.
  112.     
  113.     short        itemType;
  114.     Handle        itemHand;
  115.     Rect        itemBox;
  116.     PenState    pnState;
  117.     
  118.     GetDItem(theDialog,theItem,&itemType,&itemHand,&itemBox);
  119.     GetPenState(&pnState);
  120.     
  121.     if (((itemBox.right - itemBox.left) < 2) ||
  122.         ((itemBox.bottom - itemBox.top) < 2))
  123.     {
  124.         MoveTo(itemBox.left,itemBox.top);
  125.         
  126.         // is this horizontal?
  127.         
  128.         if ((itemBox.right - itemBox.left) > (itemBox.bottom - itemBox.top))
  129.             ThreeDLineTo(itemBox.right, itemBox.top, kRecessedEmbossed);
  130.         else
  131.             ThreeDLineTo(itemBox.left, itemBox.bottom, kRecessedEmbossed);
  132.     }
  133.     else
  134.     {
  135.         PenPat(&qd.gray);
  136.         FrameRect(&itemBox);
  137.     }
  138.     SetPenState(&pnState);
  139. }
  140.  
  141.  
  142. pascal void        EditFieldDecorator(DialogPtr theDialog,short theItem)
  143. {
  144.     // this is a handy function for performing the 3D edit field enhancement without using
  145.     // a special modal event filter. This is installed as a user item into any dummy user
  146.     // item in the dialog. When it gets drawn, this routine is called which scans the item
  147.     // list and decorates any edit fields it finds.
  148.     
  149.     Add3DDialogEffects(theDialog);
  150. }
  151.  
  152.  
  153. void    SetUniversalUserItem(DialogPtr theDialog,short theItem,ProcPtr theProc)
  154. {
  155.     // utility function to set up a user item procedure. This creates a routine descriptor
  156.     // so it works on the PowerPC. However, this also means that the routine descriptor has to
  157.     // be disposed of, so you must call DisposeUserItem as part of your clean up
  158.     
  159.     UserItemUPP        uiProc;
  160.     short            itemType;
  161.     Handle            itemHand;
  162.     Rect            itemBox;
  163.     
  164.     GetDItem(theDialog,theItem,&itemType,&itemHand,&itemBox);
  165.     if ((itemType & 0x7F) == userItem)
  166.     {
  167.         uiProc = NewUserItemProc(theProc);
  168.         itemHand = (Handle) uiProc;
  169.         SetDItem(theDialog,theItem,itemType,itemHand,&itemBox);
  170.     }
  171. }
  172.  
  173.  
  174. void    DisposeUserItem(DialogPtr theDialog,short theItem)
  175. {
  176.     // call if you allocated a routine descriptor for a user item
  177.     
  178.     UserItemUPP        uiProc;
  179.     short            itemType;
  180.     Handle            itemHand;
  181.     Rect            itemBox;
  182.     
  183.     GetDItem(theDialog,theItem,&itemType,&itemHand,&itemBox);
  184.     if ((itemType & 0x7F) == userItem)
  185.     {
  186.         uiProc = (UserItemUPP) itemHand;
  187.         DisposeRoutineDescriptor(uiProc);
  188.     }
  189. }
  190.  
  191. #ifndef __COLOURLAB__
  192.  
  193. void    DummyDialog(short dialogID)
  194. {
  195.     // this is a handy function for creating user interface mockup apps. It displays any dialog
  196.     // and handles it in a generic way. It is dismissed by an OK or Cancel button- other buttons
  197.     // have no effect but checkboxes will toggle. It will also frame all user items found
  198.  
  199.     DialogPtr        theDialog;
  200.     short            theItem,itemType,index,dCount;
  201.     Handle            itemHand;
  202.     Rect            itemBox;
  203.     UserItemUPP        uiProc;
  204.     Boolean            found1Edit = FALSE;
  205.     ModalFilterUPP    stdDialogProc;
  206.     
  207.     theDialog = GetNewDialog(dialogID,NULL,(WindowPtr) -1L);
  208.     
  209.     if (theDialog)
  210.     {
  211.         uiProc = NewUserItemProc((ProcPtr) FrameRectUserItem);
  212.         
  213.         // walk the DITL, getting user items and setting them to the framerect user item
  214.         
  215.         dCount = CountDITL(theDialog);
  216.         for (index = 1;index <= dCount;index++)
  217.         {
  218.             GetDItem(theDialog,index,&itemType,&itemHand,&itemBox);
  219.             
  220.             if ((itemType & 0x7F) == userItem)
  221.             {
  222.                 itemHand = (Handle) uiProc;
  223.                 SetDItem(theDialog,index,itemType,itemHand,&itemBox);
  224.             }
  225.             if ((itemType & 0x7F) == editText && !found1Edit)
  226.             {
  227.                 SelIText(theDialog,index,0,32767);
  228.                 found1Edit = TRUE;
  229.             }
  230.         }
  231.         StdDialogSetup(theDialog);
  232.         stdDialogProc = NewModalFilterProc((ProcPtr) StdMoveableFilterProc);
  233.         RestoreDialogLocation(theDialog,dialogID);
  234.         PutUpDialog(theDialog);
  235.         OutlineDialogItem(theDialog,ok);
  236.         theItem = 0;
  237.         
  238.         while (theItem == 0)
  239.         {
  240.             ModalDialog(stdDialogProc,&theItem);
  241.             
  242.             switch(theItem)
  243.             {
  244.                 case ok:
  245.                 case cancel:
  246.                     break;
  247.                 default:
  248.                     GetDItem(theDialog,theItem,&itemType,&itemHand,&itemBox);
  249.                     if ((itemType & 0x7F) == ctrlItem + chkCtrl)
  250.                         SetCtlValue((ControlHandle) itemHand,GetCtlValue((ControlHandle) itemHand) ^ 1);
  251.                     theItem = 0;
  252.                     break;
  253.             }
  254.         }
  255.         DisposeRoutineDescriptor(uiProc);
  256.         DisposeRoutineDescriptor(stdDialogProc);
  257.         SaveDialogLocation(theDialog,dialogID);
  258.         TakeDownDialog(theDialog);
  259.         DisposeDialog(theDialog);
  260.     }
  261. }
  262.  
  263. #endif
  264.  
  265. void    DrawDialogItem(DialogPtr theDialog,short theItem)
  266. {
  267.     short        itemType;
  268.     Handle        itemHand;
  269.     Rect        itemBox;
  270.     RgnHandle    temp;
  271.     GrafPtr        savePort;
  272.  
  273.     if (theDialog)
  274.     {
  275.         GetPort(&savePort);
  276.         SetPort(theDialog);
  277.         
  278.         GetDItem(theDialog,theItem,&itemType,&itemHand,&itemBox);
  279.         if (EmptyRect(&itemBox))
  280.             InsetRect(&itemBox,-1,-1);
  281.         RectRgn(temp = NewRgn(),&itemBox);
  282.         UpdtDialog(theDialog,temp);
  283.         DisposeRgn(temp);
  284.         
  285.         SetPort(savePort);
  286.     }
  287. }
  288.  
  289. #ifndef __COLOURLAB__
  290.  
  291. pascal Boolean    StdMoveableFilterProc(DialogPtr theDialog,EventRecord *theEvent,short *item)
  292. {
  293.     // allows ModalDialog calls to be used for Moveable Modals by passing other events to
  294.     // the main loop for handling.
  295.     
  296.     Boolean            returnValue = FALSE;
  297.     GrafPtr            savePort;
  298.     ModalFilterUPP    stdDialogProc;
  299.     OSErr            theErr;
  300.     WindowPtr        target;
  301.     short            partCode;
  302.     
  303.     switch (theEvent->what)
  304.     {
  305.         case activateEvt:
  306.             if ((WindowPtr)theEvent->message == theDialog)
  307.             {
  308.                 GetPort(&savePort);
  309.                 SetPort(theDialog);
  310.             
  311.                 theErr = GetStdFilterProc(&stdDialogProc);
  312.             
  313.                 if (theErr == noErr)
  314.                     returnValue = CallModalFilterProc(stdDialogProc,theDialog,theEvent,item);
  315.                 SetPort(savePort);
  316.             }
  317.             else
  318.             {
  319.                 HandleOneEvent(theEvent);
  320.                 returnValue = TRUE;
  321.             }
  322.             break;
  323.         case updateEvt:
  324.             if ((WindowPtr)theEvent->message == theDialog)
  325.             {
  326.                 Add3DDialogEffects(theDialog);
  327.                 OutlineDialogItem(theDialog,ok);
  328.                 returnValue = FALSE;
  329.             }
  330.             else
  331.             {
  332.                 HandleOneEvent(theEvent);
  333.                 returnValue = TRUE;
  334.             }
  335.             break;
  336.         case mouseDown:
  337.             partCode = FindWindow(theEvent->where,&target);
  338.             if ((partCode == inDrag) && (target == theDialog))
  339.             {
  340.                 HandleOneEvent(theEvent);
  341.                 returnValue = TRUE;
  342.                 break;
  343.             }
  344.             // fall through to default case if we clicked elsewhere
  345.         default:
  346.             GetPort(&savePort);
  347.             SetPort(theDialog);
  348.             
  349.             theErr = GetStdFilterProc(&stdDialogProc);
  350.             
  351.             if (theErr == noErr)
  352.             {
  353.                 returnValue = CallModalFilterProc(stdDialogProc,theDialog,theEvent,item);
  354.                 //DisposeRoutineDescriptor(stdDialogProc);
  355.             }
  356.             SetPort(savePort);
  357.             break;
  358.     }
  359.     if (gCursorTask)
  360.     {
  361.         StopCursorAnimation();
  362.         InitCursor();
  363.     }
  364.     return(returnValue);
  365. }
  366.  
  367. #endif
  368.  
  369. void    StdDialogSetup(DialogPtr theDialog)
  370. {
  371.     // installs standard info for dialog handling- i.e. default ok and cancel buttons, etc
  372.     // WARNING- make sure you only call this if you have both OK and cancel buttons or bomb!!!
  373.     
  374.     OSErr        theErr;
  375.     
  376.     theErr = SetDialogDefaultItem(theDialog,ok);
  377.     theErr = SetDialogCancelItem(theDialog,cancel);
  378.     theErr = SetDialogTracksCursor(theDialog,TRUE);
  379. }
  380.  
  381. #ifndef __COLOURLAB__
  382.     void    SaveDialogLocation(DialogPtr theDialog,short resID)
  383.     {
  384.         // saves the dialog location in the prefs file with the iD passed added to the location base
  385.         // this is to avoid confusion with the window location resources, which are very similar.
  386.         
  387.         SaveWindowLocation(theDialog,resID + kDialogLocationIDBase,TRUE,FALSE);
  388.     }
  389.     
  390.     
  391.     void    RestoreDialogLocation(DialogPtr theDialog,short resID)
  392.     {
  393.         // restores the dialog to its saved location
  394.         
  395.         (void) RestoreWindowLocation(theDialog,resID + kDialogLocationIDBase,TRUE);
  396.     }
  397. #else
  398.  
  399. #include    "CWindowSaver.h"
  400.  
  401.     void    SaveDialogLocation(DialogPtr theDialog,short resID)
  402.     {
  403.         // saves the dialog location in the prefs file with the iD passed added to the location base
  404.         // this is to avoid confusion with the window location resources, which are very similar.
  405.         
  406.         if (gWindowSaver)
  407.             gWindowSaver->SaveWindow(theDialog,resID + kDialogLocationIDBase);
  408.     }
  409.     
  410.     
  411.     void    RestoreDialogLocation(DialogPtr theDialog,short resID)
  412.     {
  413.         // restores the dialog to its saved location
  414.         if (gWindowSaver)
  415.             gWindowSaver->RestoreWindow(theDialog,resID + kDialogLocationIDBase);
  416.     }
  417. #endif
  418.  
  419. void    OffsetDialogItem(DialogPtr theDialog,short theItem,short hOffset,short vOffset)
  420. {
  421.     // moves the dialog item by the given amount, and redraws the item.
  422.  
  423.     short    itemType;
  424.     Handle    itemHand;
  425.     Rect    itemBox;
  426.     GrafPtr    savePort;
  427.     
  428.     GetPort(&savePort);
  429.     SetPort(theDialog);
  430.     
  431.     GetDItem(theDialog,theItem,&itemType,&itemHand,&itemBox);
  432.     if (theItem == ok)
  433.         InsetRect(&itemBox,-4,-4);
  434.     else
  435.         InsetRect(&itemBox,-1,-1);
  436.     EraseRect(&itemBox);
  437.     if (theItem == ok)
  438.         InsetRect(&itemBox,4,4);
  439.     else
  440.         InsetRect(&itemBox,1,1);
  441.     OffsetRect(&itemBox,hOffset,vOffset);
  442.     SetDItem(theDialog,theItem,itemType,itemHand,&itemBox);
  443.     
  444.     // if the dialog item is a control, it is necessary to offset the control rect also
  445.     
  446.     if (itemType & ctrlItem)
  447.         (*(ControlHandle) itemHand)->contrlRect = itemBox;
  448.     
  449.     DrawDialogItem(theDialog,theItem);
  450.     SetPort(savePort);
  451. }
  452.  
  453.  
  454. PopUpInfoHdl    GetDialogPopUpMenuInfo(DialogPtr theDialog,short theItem)
  455. {
  456.     short    itemType;
  457.     Handle    itemHand;
  458.     Rect    itemBox;
  459.     
  460.     GetDItem(theDialog,theItem,&itemType,&itemHand,&itemBox);
  461.     
  462.     if (((itemType & 0x7F) == (ctrlItem + resCtrl)) && (itemHand != NULL))
  463.         return((PopUpInfoHdl)(*(ControlHandle) itemHand)->contrlData);
  464.     else
  465.         return(NULL);
  466. }
  467.  
  468. #ifndef __COLOURLAB__
  469.  
  470. void            PutUpDialog(DialogPtr theDialog)
  471. {
  472.     // replacement for ShowWindow does the right thing with floaters for activate events
  473.  
  474.     ActivateFloatersAndTopDocument(FALSE);
  475.     ShowWindow(theDialog);
  476. }
  477.  
  478.  
  479. void            TakeDownDialog(DialogPtr theDialog)
  480. {
  481.     // replacement for ShowWindow does the right thing with floaters for activate events
  482.  
  483.     HideWindow(theDialog);
  484.     ActivateFloatersAndTopDocument(TRUE);
  485. }
  486.  
  487. #endif
  488.  
  489. void            Add3DDialogEffects(DialogPtr theDialog)
  490. {
  491.     // this routine is called when an update for the dialog occurrs (provided you use the std
  492.     // filter proc provided here), and adds 3D effects to the window, such as recessing any
  493.     // edit fields, etc
  494.     
  495.     short        itemCount,index,itemType;
  496.     Handle        itemHand;
  497.     Rect        itemBox;
  498.     GrafPtr        savePort;
  499.  
  500.     itemCount = CountDITL(theDialog);
  501.     GetPort(&savePort);
  502.     SetPort(theDialog);
  503.     for (index = 1;index <= itemCount;index++)
  504.     {
  505.         GetDItem(theDialog,index,&itemType,&itemHand,&itemBox);
  506.         
  507.         if ((itemType & 0x7F) == editText)
  508.         {
  509.             InsetRect(&itemBox,-3,-3);
  510.             Frame3DRect(&itemBox,kRecessedEmbossed);
  511.         }
  512.     }
  513.     SetPort(savePort);
  514. }
  515.  
  516.  
  517. void            SetFPItem(DialogPtr theDialog,short item,float x,short decPlaces)
  518. {
  519.     // sets the edit text item to a string of the floating point value passed.
  520.     
  521.     short    itemType;
  522.     Handle    itemHand;
  523.     Rect    itemBox;
  524.     decform    format;
  525.     decimal    d;
  526.     Str255    ts;
  527.     
  528.     GetDItem(theDialog,item,&itemType,&itemHand,&itemBox);
  529.     
  530.     if ((itemType & 0x7F) == editText ||
  531.         (itemType & 0x7F) == statText)
  532.     {
  533.         if (isnan(x) || ! isfinite(x))
  534.         {
  535.             ts[0] = 1;
  536.             ts[1] = 0xB0;
  537.             
  538.             SysBeep(1);
  539.         }
  540.         else
  541.         {
  542.             format.style = FIXEDDECIMAL;
  543.             format.digits = decPlaces;
  544.         
  545.             num2dec(&format,x,&d);
  546.             dec2str(&format,&d,(char*) &ts[1]);
  547.             ts[0] = strlen((char*) &ts[1]);
  548.         }
  549.         SetIText(itemHand,ts);
  550.     }
  551. }
  552.  
  553.  
  554.  
  555. float            GetFPItem(DialogPtr theDialog,short item)
  556. {
  557.     // returns the floating point value of the string in the edit field item
  558.     
  559.     short    itemType,ix,vp;
  560.     Handle    itemHand;
  561.     Rect    itemBox;
  562.     decimal    d;
  563.     Str255    ts;
  564.     
  565.     GetDItem(theDialog,item,&itemType,&itemHand,&itemBox);
  566.     
  567.     if ((itemType & 0x7F) == editText ||
  568.         (itemType & 0x7F) == statText)
  569.     {
  570.         GetIText(itemHand,ts);
  571.         
  572.         if (ts[1] == 0xB0)
  573.         {
  574.             return (1.0 / 0.0);
  575.         }
  576.         else
  577.         {
  578.             ts[ts[0] + 1] = 0;
  579.             ix = 1;
  580.             str2dec((char*) &ts,&ix,&d,&vp);    
  581.             
  582.             if (vp)
  583.                 return dec2num(&d);
  584.         }
  585.     }
  586.     return 0;
  587. }
  588.  
  589.  
  590. void    SetItemValue(DialogPtr theDialog,short theItem,short ctlValue)
  591. {
  592.     // sets the control item to value, if it is a control
  593.     
  594.     short    itemType;
  595.     Handle    itemHand;
  596.     Rect    itemBox;
  597.     
  598.     GetDItem(theDialog,theItem,&itemType,&itemHand,&itemBox);
  599.     if (itemType & ctrlItem)
  600.         SetCtlValue((ControlHandle) itemHand,ctlValue);
  601.     else
  602.     {
  603.         if (itemType & (statText + editText))
  604.         {
  605.             Str255    iText;
  606.             
  607.             NumToString(ctlValue,iText);
  608.             SetIText(itemHand,iText);
  609.         }
  610.     }
  611. }
  612.  
  613.  
  614. short    GetItemValue(DialogPtr theDialog, short theItem)
  615. {
  616.     // gets the value of the control item , if it is a control
  617.  
  618.     short    itemType;
  619.     Handle    itemHand;
  620.     Rect    itemBox;
  621.     
  622.     GetDItem(theDialog,theItem,&itemType,&itemHand,&itemBox);
  623.     if (itemType & ctrlItem)
  624.         return GetCtlValue((ControlHandle) itemHand);
  625.     else
  626.     {
  627.         if (itemType & (statText + editText))
  628.         {
  629.             long    number;
  630.             Str255    iText;
  631.             
  632.             GetIText(itemHand,iText);
  633.             StringToNum(iText,&number);
  634.             
  635.             return LoWord(number);
  636.         }
  637.         else
  638.             return -1;
  639.     }
  640. }
  641.  
  642.  
  643. void    HiliteCtlItem(DialogPtr theDialog,short theItem,short hState)
  644. {
  645.     short    itemType;
  646.     Handle    itemHand;
  647.     Rect    itemBox;
  648.     
  649.     GetDItem(theDialog,theItem,&itemType,&itemHand,&itemBox);
  650.     if (itemType & ctrlItem)
  651.         HiliteControl((ControlHandle) itemHand,hState);
  652. }
  653.  
  654.  
  655. void    DrawCTabInRect(Rect* aRect,CTabHandle aCTab)
  656. {
  657.     // draws the colour table in the rect as best it can. This is useful for previewing palettes,
  658.     // etc. Draws in the current port using RGBForeColor to set the colours.
  659.  
  660.     short        numColours,index,rows,cols,i;
  661.     Rect        pr,osRect;
  662.     PicHandle    aPic;
  663.     
  664.     
  665.     if (aCTab)
  666.     {
  667.         SetRect(&pr,0,0,8,8);
  668.         numColours = (*aCTab)->ctSize + 1;
  669.         /*
  670.         rows = numColours / 8;
  671.         (rows < 1)? cols = numColours : cols = 8;
  672.         */
  673.         cols = numColours;
  674.         rows = 1;
  675.         SetRect(&osRect,0,0,8 * cols,8 * rows);
  676.         
  677.         aPic = OpenPicture(&osRect);
  678.         index = 0;
  679.         while(rows--)
  680.         {
  681.             for(i = 0;i < cols;i++)
  682.             {
  683.                 RGBForeColor(&(*aCTab)->ctTable[index++].rgb);
  684.                 PaintRect(&pr);
  685.                 OffsetRect(&pr,8,0);
  686.             }
  687.             OffsetRect(&pr,-cols * 8,8);
  688.         }
  689.         ClosePicture();
  690.         DrawPicture(aPic,aRect);
  691.         KillPicture(aPic);
  692.     }
  693. }
  694.  
  695.  
  696. void    SetDialogFontStyle(DialogPtr theDialog,short fontID,short fontSize)
  697. {
  698.     // this changes the dialog's font and size for static and edit text items. This works by
  699.     // changing the port and TE record parameters directly. It does not change any globals
  700.     // (unlike SetDAFont) so is in force for the duration of this dialog only. Much more
  701.     // useful than anything apple ever provided. Hmmm.
  702.     
  703.     DialogPeek    dp;
  704.     TEHandle    teH;
  705.     GrafPtr        savePort;
  706.     short        saveSelStart,saveSelEnd;
  707.     
  708.     if (theDialog)
  709.     {
  710.         GetPort(&savePort);
  711.         SetPort(theDialog);
  712.         
  713.         TextFont(fontID);
  714.         TextSize(fontSize);
  715.         TextFace(0);
  716.         
  717.         dp = (DialogPeek) theDialog;
  718.         teH = dp->textH;
  719.         
  720.         if (teH)
  721.         {
  722.             TEDeactivate(teH);
  723.             saveSelStart = (*teH)->selStart;
  724.             saveSelEnd = (*teH)->selEnd;
  725.             // see if this is a styled text edit record. It is if the size field is negative.
  726.             
  727.             if ((*teH)->txSize < 0)    
  728.             {
  729.                 // changing the styles for a styled record is trickier- we need to select the
  730.                 // text and change the styles using the API, because otherwise things get
  731.                 // horrendous.
  732.                 
  733.                 TextStyle    tStyleInfo;
  734.                 RGBColor    black = {0,0,0};
  735.                 
  736.                 tStyleInfo.tsFont = fontID;
  737.                 tStyleInfo.tsFace = 0;
  738.                 tStyleInfo.tsSize = fontSize;
  739.                 tStyleInfo.tsColor = black;
  740.                 
  741.                 TESetSelect(0,32767,teH);
  742.                 TESetStyle(doFont + doSize,&tStyleInfo,FALSE,teH);
  743.             }
  744.             else
  745.             {
  746.                 // old-style record, so set fields directly
  747.                 
  748.                 (*teH)->txSize = fontSize;
  749.                 (*teH)->txFont = fontID;
  750.                 
  751.                 // set the lineheight and font ascent
  752.                 
  753.                 FontInfo fi;
  754.                 
  755.                 GetFontInfo(&fi);
  756.                 
  757.                 (*teH)->lineHeight = fi.ascent + fi.descent + fi.leading;
  758.                 (*teH)->fontAscent = fi.ascent;
  759.             }
  760.             TECalText(teH);
  761.             TESetSelect(saveSelStart,saveSelEnd,teH);
  762.             TEActivate(teH);
  763.         }
  764.         SetPort(savePort);
  765.         
  766.         if (((WindowPeek)theDialog)->visible)
  767.             DrawDialog(theDialog);
  768.     }
  769. }
  770.  
  771.  
  772.  
  773. void    Scale2Rects(Rect *theRect,Rect *refRect)
  774. {
  775.     // this function resizes <theRect> so that it will fit into <refRect>, but preserving its
  776.     // original aspect ratio. This is useful for preventing unwanted stretching of pictures
  777.     // both for creation and display of preview images. Note this also centres the rect within
  778.     // the refRect for the shorter dimension. This is the more intuitively correct behaviour
  779.  
  780.     Fixed     aspectRatio;
  781.     Rect    destFrame;
  782.     short    refWidth,refHeight;
  783.     
  784.     destFrame.top = destFrame.left = 0;
  785.     OffsetRect(theRect,-theRect->left,-theRect->top);
  786.     
  787.     refWidth = refRect->right - refRect->left;
  788.     refHeight = refRect->bottom - refRect->top;
  789.     
  790.     if (theRect->right < theRect->bottom)
  791.     {
  792.         // the rect is taller than it is wide, so we centre horizontally
  793.         
  794.         aspectRatio = FixRatio(theRect->right,theRect->bottom);
  795.         destFrame.right = FixRound(FixMul(aspectRatio,FixRatio(refHeight,1)));
  796.         destFrame.bottom = refHeight;
  797.         
  798.         OffsetRect(&destFrame,refRect->left + ((refWidth - destFrame.right) / 2),refRect->top);
  799.     }
  800.     else
  801.     {
  802.         // the rect is wider than it is tall, so we centre vertically 
  803.         
  804.         aspectRatio = FixRatio(theRect->bottom,theRect->right);
  805.         destFrame.bottom = FixRound(FixMul(aspectRatio,FixRatio(refWidth,1)));
  806.         destFrame.right = refWidth;
  807.         
  808.         OffsetRect(&destFrame,refRect->left,refRect->top + ((refHeight - destFrame.bottom) / 2));
  809.     }
  810.     *theRect = destFrame;
  811. }
  812.  
  813.  
  814. void    ConvertStatToEdit(DialogPtr theDialog,short theItem)
  815. {
  816.     // changes the static text item with the item number passed to an editable field.
  817.     short        itemType;
  818.     Handle        itemHand;
  819.     Rect        itemBox;
  820.     GrafPtr        savePort;
  821.     DialogPeek    dp;
  822.     
  823.     dp = (DialogPeek) theDialog;
  824.     
  825.     GetDItem(theDialog,theItem,&itemType,&itemHand,&itemBox);
  826.     
  827.     if ((itemType & 0x7F) == statText)
  828.     {
  829.         itemType = editText | (itemType & itemDisable);
  830.         
  831.         SetDItem(theDialog,theItem,itemType,itemHand,&itemBox);
  832.         
  833.         if (dp->editField < 0)
  834.         {
  835.             // editing is currently not enabled for this dialog, so enable it
  836.             // by making this field the focus of the editing.
  837.         
  838.             SelIText(theDialog,theItem,0,32767);
  839.         }
  840.         
  841.         GetPort(&savePort);
  842.         SetPort(theDialog);
  843.         InsetRect(&itemBox,-4,-4);
  844.         InvalRect(&itemBox);
  845.         SetPort(savePort);
  846.     }
  847. }
  848.  
  849.  
  850.  
  851. void    ConvertEditToStat(DialogPtr theDialog,short theItem)
  852. {
  853.     // changes the edit text item passed to a static text item. If this is the current edit item
  854.     // the text record is deactivated and the tab index changed.
  855.  
  856.     short        itemType,iCount,i;
  857.     Handle        itemHand;
  858.     Rect        itemBox,iBox;
  859.     GrafPtr        savePort;
  860.     DialogPeek    dp;
  861.     
  862.     dp = (DialogPeek) theDialog;
  863.     
  864.     GetDItem(theDialog,theItem,&itemType,&itemHand,&itemBox);
  865.     
  866.     if ((itemType & 0x7F) == editText)
  867.     {
  868.         itemType = statText | (itemType & itemDisable);
  869.         
  870.         SetDItem(theDialog,theItem,itemType,itemHand,&itemBox);
  871.         
  872.         if ((dp->editField + 1) == theItem)
  873.         {
  874.             // this is the current edit field, which is a bad thing. We need to make some
  875.             // other field the current one, as this one is no longer editable. To do this,
  876.             // we need to look for another edit item that can assume the focus.
  877.             
  878.             iCount = CountDITL(theDialog);
  879.             
  880.             for (i = 1;i < iCount;i++)
  881.             {
  882.                 GetDItem(theDialog,i,&itemType,&itemHand,&iBox);
  883.                 if ((itemType & 0x7F) == editText)
  884.                 {
  885.                     // found one, so switch the focus to that field
  886.                 
  887.                     SelIText(theDialog,i,0,32767);
  888.                     break;
  889.                 }
  890.             }
  891.             
  892.             if (i >= iCount)
  893.             {
  894.                 // no further fields found, so instead we have to "switch off" editing in this
  895.                 // dialog altogether. WARNING: This uses an undocumented feature of the dialog
  896.                 // manager!
  897.                 
  898.                 TESetSelect(0,0,dp->textH);    
  899.                 dp->editField = -1;
  900.             }
  901.         }
  902.         GetPort(&savePort);
  903.         SetPort(theDialog);
  904.         InsetRect(&itemBox,-4,-4);
  905.         EraseRect(&itemBox);
  906.         InvalRect(&itemBox);
  907.         SetPort(savePort);
  908.     }
  909. }
  910.  
  911.  
  912.  
  913. void    NewFieldInfo()
  914. {
  915.     if (gFieldInfo)
  916.         DisposeHandle(gFieldInfo);
  917.         
  918.     gFieldInfo = NewHandle(0);    // handle grows as records added
  919. }
  920.  
  921.  
  922. void    SetEditFieldType(DialogPtr theDialog, short theItem, short theType)
  923. {
  924.     // registers the dialog item, which must be an edit field (other items are ignored) so that
  925.     // the standard filter proc knows what characters it can allow typed there.
  926.     
  927.     Handle        itemHand;
  928.     short        itemType;
  929.     Rect        itemBox;
  930.     fieldInfo    fi;
  931.     short        numFields;
  932.     
  933.     if (gFieldInfo == NULL)
  934.         NewFieldInfo();
  935.         
  936.     GetDItem(theDialog,theItem,&itemType,&itemHand,&itemBox);
  937.     
  938.     if ((itemType & 0x7F) == editText)
  939.     {
  940.         long    gfiSize = GetHandleSize(gFieldInfo);
  941.         
  942.         numFields = gfiSize / sizeof(fieldInfo);
  943.         
  944.         SetHandleSize(gFieldInfo,gfiSize + sizeof(fieldInfo));
  945.         
  946.         
  947.         fi.fieldID = theItem;
  948.         fi.fieldType = theType;
  949.         
  950.         (* (fieldInfo**) gFieldInfo)[numFields] = fi;
  951.     }
  952. }
  953.  
  954.  
  955.  
  956. void    DisposeFieldInfo()
  957. {
  958.     if (gFieldInfo)
  959.         DisposeHandle(gFieldInfo);
  960.         
  961.     gFieldInfo = NULL;
  962. }
  963.  
  964.  
  965. Boolean        PassCharToField(DialogPeek theDialog, unsigned char theChar)
  966. {
  967.     // passes the character to the current text field, provided that the char
  968.     // is permitted by the current field type. Return indicated whether character is typeable,
  969.     // NOT whether it was legal. This is generally more useful when employing this call in
  970.     // dialog filters (its intended use!)
  971.     
  972.     Boolean    legalChar,typeableChar;
  973.     
  974.     // take a quick exit if a) the dialog has no textEdit record, or b) it has no edit fields.
  975.     
  976.     if ((theDialog->textH == NULL) ||
  977.         ! HasEditFields((DialogPtr) theDialog))
  978.         return FALSE;
  979.     
  980.     typeableChar =     (theChar >= 0x20 && theChar <= 0x7E) ||
  981.                     (theChar >= 0x80 && theChar <= 0xFF);
  982.                     
  983.     if (typeableChar)
  984.     {
  985.         short    theField     = theDialog->editField + 1;
  986.         short    rType         = GetFieldType(theField);
  987.         
  988.         switch (rType)
  989.         {
  990.             default:
  991.             case kAlphaNumericField:
  992.                 legalChar = TRUE;
  993.                 break;
  994.             case kIntegerField:
  995.                 legalChar = (theChar >= '0' && theChar <= '9');
  996.                 break;
  997.             case kFloatingPointField:
  998.                 legalChar = (theChar >= '0' && theChar <= '9') || (theChar == '.') || (theChar == '-');
  999.                 break;
  1000.             case kAlphaOnlyField:
  1001.                 legalChar = (theChar >= 'a' && theChar <= 'z') ||
  1002.                             (theChar >= 'A' && theChar <= 'Z');
  1003.             
  1004.                 break;
  1005.             case kSignedIntegerField:
  1006.                 legalChar = (theChar >= '0' && theChar <= '9') || (theChar == '-');
  1007.                 break;
  1008.             case kUnsignedFloatingField:
  1009.                 legalChar = (theChar >= '0' && theChar <= '9') || (theChar == '.');
  1010.                 break;
  1011.         }
  1012.         
  1013.         if (legalChar)
  1014.             TEKey(theChar,theDialog->textH);
  1015.         else
  1016.             SysBeep(1);
  1017.     }    
  1018.         
  1019.     return typeableChar;
  1020. }
  1021.  
  1022.  
  1023. static short    GetFieldType(short theField)
  1024. {
  1025.     // searches for the field in the field list. If found, it returns its type. If not found,
  1026.     // it returns <kAlphaNumericField>
  1027.     
  1028.     fieldInfo    fi;
  1029.     long        numFields;
  1030.     short        rType = kAlphaNumericField;
  1031.     
  1032.     if (gFieldInfo == NULL)
  1033.         return kAlphaNumericField;
  1034.         
  1035.     numFields = GetHandleSize(gFieldInfo) / sizeof(fieldInfo);
  1036.     
  1037.     while(numFields--)
  1038.     {
  1039.         fi = (* (fieldInfo**) gFieldInfo)[numFields];
  1040.         
  1041.         if (fi.fieldID == theField)
  1042.         {
  1043.             rType = fi.fieldType;
  1044.             break;
  1045.         }
  1046.     }
  1047.     
  1048.     return rType;
  1049. }
  1050.  
  1051.  
  1052. Boolean        HasEditFields(DialogPtr theDialog)
  1053. {
  1054.     short    i,itemType;
  1055.     Handle    itemHand;
  1056.     Rect    itemBox;
  1057.     Boolean    hasAField = FALSE;
  1058.     
  1059.     i = CountDITL(theDialog);
  1060.     
  1061.     while(i)
  1062.     {
  1063.         GetDItem(theDialog,i--,&itemType,&itemHand,&itemBox);
  1064.         
  1065.         if ((itemType & 0x7F) == editText)
  1066.         {
  1067.             hasAField = TRUE;
  1068.             break;
  1069.         }
  1070.     }
  1071.     
  1072.     return hasAField;
  1073. }
  1074.  
  1075.  
  1076. static short    GetItemFlags(DialogPtr theDialog, short theItem);
  1077. static void        SetItemFlags(DialogPtr theDialog, short theItem, short flags);
  1078. static void        AddDialogRef(DialogPtr theDialog, short theItem);
  1079. static void        RemoveDialogRefs(DialogPtr theDialog);
  1080.  
  1081.  
  1082. static short    GetItemFlags(DialogPtr theDialog, short theItem)
  1083. {
  1084.     // find the first occurrence of dialog and item in the list and return the associated
  1085.     // flags.
  1086.     
  1087.     short        flags = 0x8000;
  1088.     short        numEntries;
  1089.     itemInfo    info;
  1090.     
  1091.     if (gExtraDialogInfo)
  1092.     {
  1093.         numEntries = GetHandleSize((Handle) gExtraDialogInfo) / sizeof(itemInfo);
  1094.         
  1095.         while (numEntries)
  1096.         {
  1097.             info = (*gExtraDialogInfo)[--numEntries];
  1098.         
  1099.             if (info.theDlg == theDialog &&
  1100.                 info.itemID == theItem)
  1101.             {
  1102.                 flags = info.flags;
  1103.                 break;
  1104.             }
  1105.         }
  1106.     }
  1107.     
  1108.     return flags;
  1109. }
  1110.  
  1111.  
  1112. static void        SetItemFlags(DialogPtr theDialog, short theItem, short flags)
  1113. {
  1114.     short        numEntries;
  1115.     itemInfo    info;
  1116.     
  1117.     if (gExtraDialogInfo)
  1118.     {
  1119.         numEntries = GetHandleSize((Handle) gExtraDialogInfo) / sizeof(itemInfo);
  1120.         
  1121.         while (numEntries)
  1122.         {
  1123.             info = (*gExtraDialogInfo)[--numEntries];
  1124.         
  1125.             if (info.theDlg == theDialog &&
  1126.                 info.itemID == theItem)
  1127.             {
  1128.                 info.flags = flags;
  1129.                 (*gExtraDialogInfo)[numEntries] = info;
  1130.                 break;
  1131.             }
  1132.         }
  1133.     }
  1134. }
  1135.  
  1136.  
  1137. static void        AddDialogRef(DialogPtr theDialog, short theItem)
  1138. {
  1139.     // extends the handle to include a new entry and sets the entry to this item and
  1140.     // dialog. The flags are initialised to 0. Duplicates are not checked for- the caller
  1141.     // generally should.
  1142.     
  1143.     short        numEntries;
  1144.     itemInfo    info;
  1145.     
  1146.     if (gExtraDialogInfo)
  1147.     {
  1148.         numEntries = GetHandleSize((Handle) gExtraDialogInfo) / sizeof(itemInfo);
  1149.     
  1150.         SetHandleSize((Handle) gExtraDialogInfo, (numEntries + 1) * sizeof(itemInfo));
  1151.         
  1152.         if (! MemError())
  1153.         {
  1154.             info.theDlg = theDialog;
  1155.             info.itemID = theItem;
  1156.             info.flags = 0;
  1157.             
  1158.             (*gExtraDialogInfo)[numEntries] = info;
  1159.         }
  1160.     }
  1161. }
  1162.  
  1163.  
  1164. static void        RemoveDialogRefs(DialogPtr theDialog)
  1165. {
  1166.     // removes all entries from the register that pertain to this dialog. This shortens the
  1167.     // handle by one entry as each is found and moves the others up to fill any gaps. This
  1168.     // is normally done as part of the clean-up for the dialog. If the handle is emptied by
  1169.     // this operation, the caller should dispose it.
  1170.     
  1171.     short        numEntries,i,endCount;
  1172.     itemInfo    info;
  1173.     
  1174.     if (gExtraDialogInfo)
  1175.     {
  1176.         endCount = numEntries = GetHandleSize((Handle) gExtraDialogInfo) / sizeof(itemInfo);
  1177.         endCount--;
  1178.         
  1179.         // work from the bottom up, thus simplifying the closing of
  1180.         // gaps if needed.
  1181.         
  1182.         while(numEntries)
  1183.         {
  1184.             info = (*gExtraDialogInfo)[--numEntries];
  1185.             
  1186.             if (info.theDlg == theDialog)
  1187.             {
  1188.                 // this is one to snuff out, so first move up the items
  1189.                 // below this one...
  1190.                 
  1191.                 for (i = numEntries + 1; i < endCount; i++)
  1192.                     (*gExtraDialogInfo)[i] = (*gExtraDialogInfo)[i + 1];
  1193.                 
  1194.                 // ...now shorten the handle
  1195.                 
  1196.                 SetHandleSize((Handle) gExtraDialogInfo, endCount * sizeof(itemInfo));
  1197.                 endCount--;
  1198.             }
  1199.         }    
  1200.     }    
  1201. }
  1202.  
  1203.  
  1204. void        InitFunkyDialog(DialogPtr theDialog)
  1205. {
  1206.     if (gExtraDialogInfo == NULL)
  1207.         gExtraDialogInfo = (itemInfo**) NewHandle(0);
  1208. }
  1209.  
  1210.  
  1211. void        DisposeFunkyDialog(DialogPtr theDialog)
  1212. {
  1213.     if (gExtraDialogInfo)
  1214.     {
  1215.         RemoveDialogRefs(theDialog);
  1216.         
  1217.         if (GetHandleSize((Handle) gExtraDialogInfo) == 0)
  1218.         {
  1219.             DisposeHandle((Handle) gExtraDialogInfo);
  1220.             gExtraDialogInfo = NULL;
  1221.         }
  1222.     }    
  1223. }
  1224.  
  1225.  
  1226. void        GreyOutItem(DialogPtr theDialog, short theItem)
  1227. {
  1228.     // this marks the given item as greyed out, and posts an update for it. The standard
  1229.     // filter will pick this up and grey out the item. For edit text items, the item is
  1230.     // converted to static text and the border refreshed.
  1231.     
  1232.     short    itemType,flags;
  1233.     Handle    itemHand;
  1234.     Rect    itemBox;
  1235.     GrafPtr    savePort;
  1236.     
  1237.     if (gExtraDialogInfo)
  1238.     {
  1239.         GetDItem(theDialog, theItem, &itemType, &itemHand, &itemBox);
  1240.  
  1241.         if (itemType & ctrlItem)
  1242.             HiliteCtlItem(theDialog, theItem, 255);
  1243.         else
  1244.         {
  1245.             // is the item registered with us?
  1246.             
  1247.             flags = GetItemFlags(theDialog, theItem);
  1248.             if (flags < 0)
  1249.             {
  1250.                 AddDialogRef(theDialog, theItem);
  1251.                 flags = 0;
  1252.             }
  1253.             
  1254.             // if an edit text item, convert to static
  1255.             
  1256.             
  1257.             if ((itemType & 0x7F) == editText)
  1258.             {
  1259.                 ConvertEditToStat(theDialog, theItem);
  1260.                 InsetRect(&itemBox, -4, -4);
  1261.                 
  1262.                 flags |= kWasEditTextItem;
  1263.             }
  1264.             
  1265.             // flag the item as greyed out 
  1266.             
  1267.             flags |= kGreyedOut;
  1268.             SetItemFlags(theDialog, theItem, flags);
  1269.  
  1270.             GetPort(&savePort);
  1271.             SetPort(theDialog);
  1272.             
  1273.             InvalRect(&itemBox);
  1274.             SetPort(savePort);
  1275.         }
  1276.     }    
  1277. }
  1278.  
  1279.  
  1280. void        UngreyOutItem(DialogPtr theDialog, short theItem)
  1281. {
  1282.     short    itemType,flags;
  1283.     Handle    itemHand;
  1284.     Rect    itemBox;
  1285.     GrafPtr    savePort;
  1286.     
  1287.     if (gExtraDialogInfo)
  1288.     {
  1289.         GetDItem(theDialog, theItem, &itemType, &itemHand, &itemBox);
  1290.         
  1291.         if (itemType & ctrlItem)
  1292.             HiliteCtlItem(theDialog, theItem, 0);
  1293.         else
  1294.         {
  1295.             // is the item registered with us?
  1296.             
  1297.             flags = GetItemFlags(theDialog, theItem);
  1298.             if (flags < 0)
  1299.                 return;        // never heard of it, guv.
  1300.             
  1301.             // if was previously an edit text item, convert back to edit
  1302.             
  1303.             if (((itemType & 0x7F) == statText) && (flags & kWasEditTextItem))
  1304.             {
  1305.                 ConvertStatToEdit(theDialog, theItem);
  1306.                 InsetRect(&itemBox, -4, -4);
  1307.                 
  1308.                 flags &= ~kWasEditTextItem;
  1309.             }
  1310.             
  1311.             // flag the item as no longer greyed out 
  1312.             
  1313.             flags &= ~kGreyedOut;
  1314.             SetItemFlags(theDialog, theItem, flags);
  1315.             
  1316.             GetPort(&savePort);
  1317.             SetPort(theDialog);
  1318.             
  1319.             InvalRect(&itemBox);
  1320.             SetPort(savePort);
  1321.         }
  1322.     }    
  1323. }
  1324.  
  1325.  
  1326. void        DrawGreyItem(DialogPtr theDialog, short theItem)
  1327. {
  1328.     short        itemType,flags;
  1329.     Handle        itemHand;
  1330.     Rect        itemBox;
  1331.     GrafPtr        savePort;
  1332.     Pattern        grayPat = {0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55};
  1333.     
  1334.     GetPort(&savePort);
  1335.     SetPort(theDialog);
  1336.     
  1337.     GetDItem(theDialog, theItem, &itemType, &itemHand, &itemBox);
  1338.     flags = GetItemFlags(theDialog, theItem);
  1339.     
  1340.     PenNormal();
  1341.     
  1342.     // if this was previously an edit text item, draw a border before greying it out
  1343.     
  1344.     if (((itemType & 0x7F) == statText) && (flags & kWasEditTextItem))
  1345.     {
  1346.         InsetRect(&itemBox, -3, -3);
  1347.         FrameRect(&itemBox);
  1348.     }
  1349.     
  1350.     PenMode(srcBic);
  1351.     PenPat(&grayPat);
  1352.     PaintRect(&itemBox);
  1353.     PenNormal();
  1354.     
  1355.     SetPort(savePort);    
  1356. }
  1357.  
  1358.  
  1359.  
  1360. void    UpdateGreyedItems(DialogPtr theDialog)
  1361. {
  1362.     // draws the greyed out items by calling DrawGreyItem for each one so marked in the
  1363.     // registry. Call AFTER drawing the dialog items in an update.
  1364.  
  1365.     short        numEntries, i;
  1366.     itemInfo    info;
  1367.     
  1368.     if (gExtraDialogInfo)
  1369.     {
  1370.         numEntries = GetHandleSize((Handle) gExtraDialogInfo) / sizeof(itemInfo);
  1371.     
  1372.         for (i = 0; i < numEntries; i++)
  1373.         {
  1374.             info = (*gExtraDialogInfo)[i];
  1375.             
  1376.             if ((info.theDlg == theDialog) && (info.flags & kGreyedOut))
  1377.                 DrawGreyItem(theDialog, info.itemID);
  1378.         }
  1379.     }
  1380. }
  1381.  
  1382.  
  1383. void        ZoomToDialog(DialogPtr theDialog, Rect* fromRect)
  1384. {
  1385.     // draws a zoom open effect. Requires drag manager.
  1386.  
  1387.     generalPrefHdl    gpH;
  1388.     Boolean            zoom = TRUE;
  1389.     
  1390.     gpH = (generalPrefHdl) GetPrefResource('GENP',128);
  1391.     
  1392.     if (gpH)
  1393.     {
  1394.         zoom = (*gpH)->zoomFX;
  1395.         DisposeHandle((Handle) gpH);
  1396.     }
  1397.     
  1398.     if (zoom && gImportFlags.hasDragManager)
  1399.     {
  1400.         // to find out where to zoom to, we need to get the rect of the dialog that
  1401.         // is about to come up. However, it is not actually visible at this point,
  1402.         // so we can't use FrontWindow(). Thus we need to sneak a skanky look at the
  1403.         // windowlist. This is a no-no under Copland, so we use the recommended macro.
  1404.         
  1405.         WindowPtr    tw;
  1406.         Rect        src, dest;
  1407.         
  1408.         if (theDialog)
  1409.         {
  1410.             if (fromRect == NULL)
  1411.                 src = gDialogZoomRect;
  1412.             else
  1413.                 src = *fromRect;
  1414.                 
  1415.             GetWStructRect(theDialog, &dest);
  1416.         
  1417.             (void) ZoomRects(&src, &dest, 10, zoomAccelerate);
  1418.         }
  1419.     }
  1420. }
  1421.  
  1422.  
  1423. void        ZoomFromDialog(DialogPtr theDialog, Rect* toRect)
  1424. {
  1425.     // draws a zoom close effect- requires drag manager.
  1426.  
  1427.     generalPrefHdl    gpH;
  1428.     Boolean            zoom = TRUE;
  1429.     
  1430.     gpH = (generalPrefHdl) GetPrefResource('GENP',128);
  1431.     
  1432.     if (gpH)
  1433.     {
  1434.         zoom = (*gpH)->zoomFX;
  1435.         DisposeHandle((Handle) gpH);
  1436.     }
  1437.     
  1438.     if (zoom && gImportFlags.hasDragManager)
  1439.     {
  1440.         Rect        src, dest;
  1441.         
  1442.         if (theDialog)
  1443.         {
  1444.             if (toRect == NULL)
  1445.                 src = gDialogZoomRect;
  1446.             else
  1447.                 src = *toRect;
  1448.                 
  1449.             GetWStructRect(theDialog, &dest);
  1450.             
  1451.             // make sure it really is a dialog before hiding it
  1452.             
  1453.             if (((WindowPeek) theDialog)->windowKind == dialogKind)
  1454.                 HideWindow(theDialog);
  1455.         
  1456.             //(void) ZoomRects(&dest, &src, 10, zoomDecelerate);
  1457.             
  1458.             // make a chore to do the work, so updates are processed properly
  1459.             // N.B. The chore disposes of itself once it has executed.
  1460.             
  1461.             CZoomChore*    aZChore = TCL_NEW(CZoomChore, (&dest, &src));
  1462.             gApplication->AssignIdleChore(aZChore);
  1463.         }
  1464.     }
  1465. }
  1466.  
  1467.  
  1468.  
  1469. void        GetWStructRect(WindowPtr aWindow, Rect* aRect)
  1470. {
  1471.     // returns the structure rectangle of a window, whether visible or not.
  1472.  
  1473.     Rect    r;
  1474.     Point    savedLoc;
  1475.     GrafPtr    savePort;
  1476.     
  1477.     if (! ((WindowPeek) aWindow)->visible)
  1478.     {
  1479.         // window hidden, so struc rgn is not valid. save its location, and then
  1480.         // move it offscreen, make it visible, get the rect, then put it all back.
  1481.         
  1482.         GetPort(&savePort);
  1483.         SetPort(aWindow);
  1484.         
  1485.         // record its position
  1486.         
  1487.         savedLoc = topLeft(aWindow->portRect);
  1488.         LocalToGlobal(&savedLoc);
  1489.         
  1490.         // move it halfway to infinity
  1491.         
  1492.         MoveWindow(aWindow, savedLoc.h, 0x4000, FALSE);
  1493.         ShowHide(aWindow, TRUE);
  1494.         
  1495.         r = (*((WindowPeek) aWindow)->strucRgn)->rgnBBox;
  1496.         
  1497.         // now put it all back
  1498.         
  1499.         ShowHide(aWindow, FALSE);
  1500.         MoveWindow(aWindow, savedLoc.h, savedLoc.v, FALSE);
  1501.         
  1502.         // compensate for window offset
  1503.         
  1504.         OffsetRect(&r, 0, savedLoc.v - 0x4000);
  1505.         SetPort(savePort);
  1506.     }
  1507.     else
  1508.         r = (*((WindowPeek) aWindow)->strucRgn)->rgnBBox;
  1509.         
  1510.     *aRect = r;
  1511. }
  1512.  
  1513.  
  1514.  
  1515. void    SetZoomSrcToItem(DialogPtr theDialog, short item)
  1516. {
  1517.     short    itemType;
  1518.     Handle    itemHand;
  1519.     Rect    itemBox;
  1520.     GrafPtr    savePort;
  1521.     
  1522.     if (theDialog)
  1523.     {
  1524.         GetDItem(theDialog, item, &itemType, &itemHand, &itemBox);
  1525.         
  1526.         GetPort(&savePort);
  1527.         SetPort(theDialog);
  1528.         
  1529.         InsetRect(&itemBox, 4, 4 );
  1530.         
  1531.         LocalToGlobal(&topLeft(itemBox));
  1532.         LocalToGlobal(&botRight(itemBox));
  1533.         
  1534.         gDialogZoomRect = itemBox;
  1535.  
  1536.         SetPort(savePort);
  1537.     }
  1538. }
  1539.  
  1540.  
  1541.